package device

import chisel3._
import chisel3.util._
import common.Constants._
import bus._
import utils._

trait UARTREG {
  val RHR = 0    // Receive Holding Register (read mode)
  val THR = 0    // Transmit Holding Register (write mode)
  val DLL = 0    // LSB of Divisor Latch (write mode)
  val IER = 1    // Interrupt Enable Register (write mode)
  val DLM = 1    // MSB of Divisor Latch (write mode)
  val FCR = 2    // FIFO Control Register (write mode)
  val ISR = 2    // Interrupt Status Register (read mode)
  val LCR = 3    // Line Control Register
  val MCR = 4    // Modem Control Register
  val LSR = 5    // Line Status Register
  val MSR = 6    // Modem Status Register
  val SPR = 7    // ScratchPad Register
}

class AXI4UART extends AXI4SlaveModule(new AXI4) with UARTREG {

  val wdata = Wire(UInt(8.W))
  val wen = in.w.fire()   //Wire(Bool())
  val wIdx = waddr(2, 0)
  val rIdx = raddr(2, 0)


  val reg0 = RegEnable(next = wdata, init = 0.U(8.W), wen && wIdx === THR.U)
  val reg1 = RegEnable(next = wdata, 0.U(8.W), wen && wIdx === IER.U)
  val reg2 = RegEnable(next = wdata, 0.U(8.W), wen && wIdx === FCR.U)
  val reg3 = RegEnable(next = wdata, 0.U(8.W), wen && wIdx === LCR.U)
  val reg4 = RegEnable(next = wdata, 0.U(8.W), wen && wIdx === MCR.U)
  val reg5 = RegEnable(next = wdata, 32.U(8.W), wen && wIdx === LSR.U )
  val reg6 = RegEnable(next = wdata, init = 0.U(8.W), wen && wIdx === MSR.U)
  val reg7= RegEnable(next = wdata, init = 0.U(8.W), wen && wIdx === SPR.U)

  val wshift = wIdx << 3
  wdata := (in.w.bits.data >> wshift)(7, 0)
  when(wen && wIdx === THR.U ){
    printf("%c", wdata)
  }


  val regData = MuxCase(0.U, Array(
    (rIdx === THR.U)  -> reg0,
    (rIdx === IER.U)  -> reg1,
    (rIdx === FCR.U)  -> reg2,
    (rIdx === LCR.U)  -> reg3,
    (rIdx === MCR.U)  -> reg4,
    (rIdx === LSR.U)  -> reg5,
    (rIdx === MSR.U)  -> reg6,
    (rIdx === SPR.U)  -> reg7
  ))
  val rshift = rIdx << 3
  in.r.bits.data := regData << rshift

  //  val mapping = Map(
//    RegMap(THR, reg0, putc),
//    RegMap(IER, reg1),
//    RegMap(FCR, reg2),
//    RegMap(LCR, reg3),
//    RegMap(MCR, reg4),
//    RegMap(LSR, reg5),
//    RegMap(MSR, reg6),
//    RegMap(SPR, reg7)
//  )
//def putc(c: UInt): UInt = {
//    printf("%c", c(7,0));
//    c
//  }
//  RegMap.generate(mapping, raddr(3,0), in.r.bits.data,
//    waddr(3,0), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb >> waddr(log2Ceil(DataBytes)-1,0)))


  // val reg_busy = RegInit(false.B)

  // io.in_axi4.w.ready := !reg_busy

  // when(io.in_axi4.aw.fire()){
  //   reg_busy := true.B
  // }.elsewhen(io.in_axi4.w.fire()){
  //   reg_busy := false.B
  //   io.in_axi4.b.valid := true.B
  // }
  // when(io.in.ar.fire()){
  //   printf("addr req\n")
  // }

  // when(io.in.w.fire()){
  //   val wdata = io.in.w.bits.DATA //>> (waddr(2, 0) << 3)
  //   printf("%c", wdata(7, 0))
  // }
  
}
